
/**
 * Crea una instancia de una lista de órdenes de trabajo.
 *
 * @constructor
 * @this {ListaOTUteco}
 * @param {string} parentId El valor del tag 'id' del elemento HTML que va a contener la lista.
 * @param {string} tipo Un string que indica el tipo de lista ('newlong' o 'uteco').
 */
function ListaOTUteco(parentId, tipo)
	{
	this.parentId = parentId;
	this.tipo = tipo;
	this.ordenes = new Array();
	
	this.etapas = null;
	this.fechaInicio = null;
	this.fechaFin = null;
	this.capacidad = 0;
	this.cambio = false;
	}

/**
 * Establece las órdenes de la lista. 
 * Dependiendo del tipo ('uteco' o 'newlong') cada objeto de la lista debe tener definidas diferentes propiedades:
 * - Uteco: 'id', 'identificador', 'metros', 'tipoPapel', 'manija', 'cantidadColores', 'lavaUv', 'barniz', 'formato' y 'logotipo'.
 * - Newlong: 'id', 'identificador', 'newlong', 'cicloNewlongNumero', 'cicloNewlongId', 'formato', 'tipoPapel', 'bolsas', 'manija', 'logotipo' y 'fechaPrometida'.
 * 
 * @this {ListaOTUteco}
 * @param {Array} orders Las ordenes de la lista.
 */
ListaOTUteco.prototype.setOrdenes = function(orders)
	{this.ordenes = orders;};
	
/**
 * Devuelve las órdenes de la lista.
 *
 * @this {ListaOTUteco}
 * @return {Array} Las órdenes de la lista.
 */
ListaOTUteco.prototype.getOrdenes = function()
	{return this.ordenes;};

/**
 * Establece las etapas de la lista (las etapas solo tienen sentido cuando la lista es del tipo 'newlong').
 * Cada objeto del array debe tener definidas las propiedades: 'formatoId', 'formato', 'cantidad' y 'orden'.
 * 
 * @this {ListaOTUteco}
 * @param {Array} stages Las etapas de la lista.
 */
ListaOTUteco.prototype.setEtapas = function(stages)
	{
	this.etapas = stages;
	
	for(var i=0; i<this.etapas.length; i++)
		{
		this.etapas[i]['cantidad'] = parseInt(this.etapas[i]['cantidad'], 10);
		this.etapas[i]['orden'] = parseInt(this.etapas[i]['orden'], 10);
		}
	};

/**
 * Devuelve un array donde los índices es el formato y los valores son su orden.
 * 
 * @this {ListaOTUteco}
 * @return {Object} El orden de cada formato.
 */
ListaOTUteco.prototype.getOrdenFormatos = function()
	{
	var res = new Object();
	if(this.etapas != null)
		{
		for(var i=0; i<this.etapas.length; i++)
			{res[this.etapas[i]['formato']] = this.etapas[i]['orden'];}
		}
	return res;
	};
	
/**
 * Establece la fecha de inicio del ciclo al que pertenecen las órdenes.
 * 
 * @this {ListaOTUteco}
 * @param {Date} startDate La fecha de inicio.
 */
ListaOTUteco.prototype.setFechaInicio = function(startDate)
	{this.fechaInicio = startDate;};
	
/**
 * Establece la fecha de fin del ciclo al que pertenecen las órdenes.
 * 
 * @this {ListaOTUteco}
 * @param {Date} endDate La fecha de fin.
 */
ListaOTUteco.prototype.setFechaFin = function(endDate)
	{this.fechaFin = endDate;};
	
/**
 * Establece la capacidad del ciclo al que pertenecen las órdenes.
 * 
 * @this {ListaOTUteco}
 * @param {number} capacity La capacidad.
 */
ListaOTUteco.prototype.setCapacidad = function(capacity)
	{
	this.capacidad = capacity;

	// Verifico si no debo recalcular las cantidades de las etapas.
	if(this.etapas != null)
		{
		var total = 0;	
		for(var i=0; i<this.etapas.length; i++)
			{total += this.etapas[i]['cantidad'];}
			
		if(total != this.capacidad)
			{
			var indice = this.capacidad / total;
			for(var j=0; j<this.etapas.length; j++)
				{this.etapas[j]['cantidad'] = parseInt(indice * this.etapas[j]['cantidad'], 10);}
			this.calcularDisponibles();
			}
		}
	};

/**
 * Devuelve un booleano indicando si se realizaron cambios en el orden de la lista.
 * 
 * @this {ListaOTUteco}
 * @return {boolean} 'true' si se realizó un cambio o 'false' en caso contrario.
 */
ListaOTUteco.prototype.huboCambios = function()
	{return this.cambio;};
	
/**
 * Devuelve la lista de los id's de las ordenes, en un string, separados por una coma.
 *
 * @this {ListaOTUteco}
 * @return {String} La lista de id's.
 */
ListaOTUteco.prototype.getIds = function()
	{
	var res = '', c = 0;
	jQuery("#" + this.parentId + " ul li.orden").each(function(index)
		{
		var ordenId = jQuery(this).attr("data-ordenId");
		if(ordenId != 0 && ordenId != '0')
			{
			if(res.length > 0) res += ',';
			res += jQuery(this).attr("data-ordenId") + ":" + c;
			c++;
			}
		});
	return res;
	};
	
/**
 * Devuelve la lista de los formatos, en un string, separados por una coma.
 *
 * @this {ListaOTUteco}
 * @return {String} La lista de id's.
 */
ListaOTUteco.prototype.getIdsFormatos = function()
	{
	var res = '';

	var c = 0;
	var ultimo = '';
	jQuery("#" + this.parentId + " ul li.orden").each(function(index)
		{
		var formato = jQuery(this).attr("data-formato");
		if(formato != ultimo)
			{
			if(res.length > 0) res += ',';
			res += formato + ":" + c;
			
			ultimo = formato;
			c++;
			}
		});
	
	return res;
	};

/**
 * Genera el código Html de la lista, lo inserta en la página y le asigna los comportamientos.
 *
 * @this {ListaOTUteco}
 */
ListaOTUteco.prototype.insertarHtml = function()
	{
	// Genero y inserto el código Html.
	var html = this.generarHtml();
	jQuery("#" + this.parentId).children().remove();
	jQuery("#" + this.parentId).append(html);
	this.moverOrdenesVacias();

	// Asigno los comportamientos y calculo las fechas.
	this.asignarComportamientos();
	if(this.tipo == 'newlong')
		{this.juntarFormatos(null);}
	else
		{this.calcularFechasYDisponible();}
	};

/**
 * Genera el código Html de la lista.
 *
 * @private
 * @this {ListaOTUteco}
 * @return {string} El código Html
 */
ListaOTUteco.prototype.generarHtml = function()
	{
	var o, html = '<ul class="ordenes">';
	
	if(this.tipo == 'uteco')
		{
		for(o=0; o<this.ordenes.length; o++)
			{
			var barniz = 0;
                        if (this.ordenes[o].barniz){ barniz = 1}
                        var cuerpos = parseInt(this.ordenes[o].cantidadColores) + barniz;
                        html += '<li class="orden" data-ordenId="' + this.ordenes[o].id + '" data-metros="' + this.ordenes[o].metros + '">';
			html += '<span class="identificador">Orden ' + this.ordenes[o].identificador + '</span>';
			html += ' - <span class="info">' + formatoNumero(this.ordenes[o].metros) + ' mts</span> - ' 
											 + '<span class="fechas"></span>';
			html += '<div style="text-align:right;"><span class="info_adicional">'
						+ this.ordenes[o].logotipo + ' - '
						+ this.ordenes[o].lacaUv + ' - '
						+ ((this.ordenes[o].barniz == true || this.ordenes[o].barniz == 'true')? 'Con barniz' : 'Sin barniz' ) + ' - '
						+ this.ordenes[o].formato + ' ' +
                                                 ' Cuerpos: ' + cuerpos
                                                 + ' Lleva Uv: ' + (this.ordenes[o].lacaUvId == 3 ? 'Si' : 'No' )
						+ '</span></div>';
			html += '</li>';
			}	
		}
	else
		{
		for(o=0; o<this.ordenes.length; o++)
			{
			html += '<li class="orden" data-ordenId="' + this.ordenes[o].id
										 + '" data-bolsas="' + this.ordenes[o].bolsas
										 + '" data-formato="' + this.ordenes[o].formato
										 + '" data-tipoPapel="' + this.ordenes[o].tipoPapel + '">';
			html += ' ' + this.ordenes[o].formato;
			html += ' - <span class="identificador">Orden ' + this.ordenes[o].identificador + '</span>';
			html += ' - <span class="info">' + formatoNumero(this.ordenes[o].bolsas) + ' bolsas</span> - '
											 + '<span class="fechas"></span>';
			html += '<div style="text-align:right;"><span class="info_adicional">'
						+ this.ordenes[o].logotipo + ' - '
						+ this.ordenes[o].tipoPapel + ' - '
						+ this.ordenes[o].manija + ' - Prometido: '
						+ this.ordenes[o].fechaPrometida
						+ '</span></div>';
			html += '</li>';
			}

		
		}
		
	html += '</ul>';			
	return html;
	};

/**
 * Asigna los eventos y comportamientos al código Html de la lista.
 *
 * @private
 * @this {ListaOTUteco}
 */
ListaOTUteco.prototype.asignarComportamientos = function()
	{
	var padreId = this.parentId;
	var lot = this;

	jQuery("#" + padreId + " ul").sortable(
		{
		stop: function(event, ui)
			{
			// Verifico que la orden vacia este al final de todo.
			lot.moverOrdenesVacias();

			if(lot.tipo == 'uteco')
				{
				// Recalculo las fechas.
				lot.calcularFechasYDisponible();
				}
			else
				{
				// Junto todos los formatos y recalculo las fechas.
				lot.juntarFormatos(ui.item);
				}

			// Establezco que hubo un cambio.
			lot.cambio = true;
			}
		});			
	};

/**
 * Ordena los elementos de la lista.
 *
 * @this {ListaOTUteco}
 */
/**ListaOTUteco.prototype.ordenar = function()
	{
	if(this.ordenes != null)
		{
		if(this.tipo == 'uteco')
			{
			this.ordenes.sort(function(ot1, ot2)
                        	{
                                if(ot1['lacaUv'] < ot2['lacaUv']) return -1;
				else if(ot1['lacaUv'] > ot2['lacaUv']) return 1;
				else if(ot1['barniz'] < ot2['barniz']) return -1;
				else if(ot1['barniz'] > ot2['barniz']) return 1;
				else if(ot1['formato'] < ot2['formato']) return -1;
				else if(ot1['formato'] > ot2['formato']) return 1;
				return 0;
				});
			}
		else
			{
			var formatOrders = this.getOrdenFormatos();
			
			this.ordenes.sort(function(ot1, ot2)
				{
				// Comparo por el formato.
				if(formatOrders != null)
					{
					if(formatOrders[ot1['formato']] != undefined && 
					   formatOrders[ot2['formato']] != undefined &&
					   formatOrders[ot1['formato']] != formatOrders[ot2['formato']])
						{return parseInt(formatOrders[ot1['formato']],10) - parseInt(formatOrders[ot2['formato']],10);}
					}
				else
					{
					if(ot1['formato'] != ot2['formato'])
						{
						if(ot1['formato'] < ot2['formato']) return -1;
						if(ot1['formato'] > ot2['formato']) return 1;	
						}
					}
				
				var t1 = convertirFecha(ot1['fechaPrometida']);
				var t2 = convertirFecha(ot2['fechaPrometida']);
				if(t1 != null && t2 != null)
					{
					if(t1.getTime() < t2.getTime()) return -1;
					if(t1.getTime() > t2.getTime()) return 1;
					}
				if(ot1['tipoPapel'] < ot2['tipoPapel']) return -1;
				if(ot1['tipoPapel'] > ot2['tipoPapel']) return 1;
                                return 0;
				});	
			}
		}
	};

/**
 * Calcular fechas y cantidad disponible.
 *
 * @this {ListaOTUteco}
 */
/**ListaOTUteco.prototype.calcularFechasYDisponible = function()
	{
	var tipo = this.tipo;
	var fechaFinCiclo = this.fechaFin;
	var fechaInicioCiclo = this.fechaInicio;
	
	// Calculo la/s cantidad/es disponible.
	this.calcularDisponibles();

	// Calculo las fechas.
	var acumulado = 0;
	var msXmts = (fechaFinCiclo - fechaInicioCiclo.getTime())/this.capacidad;
	var endDate, startDate = fechaInicioCiclo;
	jQuery("#" + this.parentId + " ul li.orden").each(function(index)
		{
		// Calculo las fechas.
		var cant = (tipo == 'uteco')? parseInt(jQuery(this).attr("data-metros"), 10) : parseInt(jQuery(this).attr("data-bolsas"), 10);
		acumulado += cant;
		endDate = new Date(fechaInicioCiclo.getTime() + msXmts*acumulado);
		
		// Inserto el codigo html.
		var span = jQuery(this).find("span.fechas");
		jQuery(span).children().remove();
		jQuery(span).append( '<span>' + startDate.getDate() + '/' + (startDate.getMonth()+1) + '/' + startDate.getFullYear() + ' <span class="hora">' + startDate.getHours() + ':' + startDate.getMinutes() + '</span>' +
							 ' - ' + endDate.getDate() + '/' + (endDate.getMonth()+1) + '/' + endDate.getFullYear() + ' <span class="hora">' + endDate.getHours() + ':' + endDate.getMinutes() + '</span>' + '</span>');

		startDate = endDate;
		});	
	};

/**
 * Calcula las cantidades disponibles
 *
 * @private
 * @this {ListaOTUteco}
 */
/**ListaOTUteco.prototype.calcularDisponibles = function()
	{
	var ocupado, disponible, liVacio, formato;
	
	if(this.tipo == 'uteco')
		{
		ocupado = 0;
		jQuery("#" + this.parentId + " ul li.orden").each(function()
			{
			var cant = parseInt(jQuery(this).attr("data-metros"), 10);
			if(jQuery(this).attr("data-ordenId") != '0') ocupado += cant;
			});
	
		disponible = this.capacidad - ocupado;
		liVacio = jQuery("#" + this.parentId + " ul li[data-ordenId='0']");
		jQuery(liVacio).attr("data-metros", disponible);
		jQuery(liVacio).find("span.disponible").children().remove();
		jQuery(liVacio).find("span.disponible").append('<span>'+formatoNumero(disponible)+'</span>');			
		}
	else
		{
		if(this.etapas != null)
			{
			for(var e=0; e<this.etapas.length; e++)
				{
				formato = this.etapas[e]['formato'];
				
				ocupado = 0;
				jQuery("#" + this.parentId + " ul li.orden[data-formato='"+formato+"']").each(function()
					{
					var cant = parseInt(jQuery(this).attr("data-bolsas"), 10);
					if(jQuery(this).attr("data-ordenId") != '0') ocupado += cant;
					});

				disponible = this.etapas[e]['cantidad'] - ocupado;
				liVacio = jQuery("#" + this.parentId + " ul li[data-ordenId='0'][data-formato='"+formato+"']");
				jQuery(liVacio).attr("data-bolsas", disponible);
				jQuery(liVacio).find("span.disponible").children().remove();
				jQuery(liVacio).find("|").append('<span>'+formatoNumero(disponible)+'</span>');
				}
			}
		}
	};

/**
 * Ordena las ordenes para juntar todos los formatos
 * 
 * @private
 * @this {ListaOTUteco}
 * @param {object} orden La orden que acaba de moverse.
 */
ListaOTUteco.prototype.juntarFormatos = function(orden)
	{
	// Obtengo un array con los items de la lista.
	var items = new Array();
	jQuery("#" + this.parentId + " ul li.orden").each(function(index)
		{
		items[index] = new Object();
		items[index]['formato'] = jQuery(this).attr("data-formato");
		items[index]['ordenId'] = jQuery(this).attr("data-ordenId");
		});

	// Obtengo las posiciones de cada formato.
	var posiciones = new Object();
	for(var i=0; i<items.length; i++)
		{
		if(orden != null)
			{
			if(items[i]['formato'] != jQuery(orden).attr("data-formato"))
				{
				if(posiciones[items[i]['formato']] === undefined)
					{posiciones[items[i]['formato']] = i;}
				}
			else
				{
				if(items[i]['ordenId'] == jQuery(orden).attr("data-ordenId"))
					{posiciones[items[i]['formato']] = i;}
				}
			}
		else
			{
			if(items[i]['ordenId'] == 0 || items[i]['ordenId'] == '0')
				{posiciones[items[i]['formato']] = i;}				
			}
		}	

	// Ordeno el array de items.
	items.sort(function(item1, item2)
		{
		var res = 0;		
		if(item1.formato != item2.formato)
			{res = posiciones[item1.formato] - posiciones[item2.formato];}
		return res;
		});

	// Reacomodo los items de acuerdo a las posiciones del array ordenado.
	for(var j=0; j<items.length; j++)
		{
		var li_j = jQuery("#" + this.parentId + " ul li.orden[data-formato='"+items[j].formato+"'][data-ordenId='"+items[j].ordenId+"']");
		var li_n = jQuery("#" + this.parentId + " ul li.orden:eq("+j+")");

		if(jQuery(li_n).attr("data-formato") != items[j].formato || jQuery(li_n).attr("data-ordenId") != items[j].ordenId)
			{jQuery(li_j).insertBefore(jQuery(li_n));}		
		}
		
	// Calculo las fechas.
	this.calcularFechasYDisponible();
	};


/**
 * Mueve la/s orden/es vacia/s (que contiene/n la cantidad disponible) al final de su etapa.
 * 
 * @private
 * @this {ListaOTUteco}
 */
ListaOTUteco.prototype.moverOrdenesVacias = function()
	{
	var ultima, ultimaId, vacia;
	
	if(this.tipo == 'uteco')
		{
		ultima = jQuery("#" + this.parentId + " ul li.orden:last");
		ultimaId = jQuery(ultima).attr("data-ordenId");
		
		if(ultimaId != 0 && ultimaId != '0')
			{
			vacia = jQuery("#" + this.parentId + " ul li.orden[data-ordenId='0']");
			jQuery(vacia).insertAfter(jQuery(ultima));
			}			
		}
	else
		{
		for(var i=0; i<this.etapas.length; i++)
			{
			var formato = this.etapas[i]['formato'];
			
			ultima = jQuery("#" + this.parentId + " ul li.orden[data-formato='"+formato+"']:last");
			ultimaId = jQuery(ultima).attr("data-ordenId");		
			if(ultimaId != 0 && ultimaId != '0')
				{
				vacia = jQuery("#" + this.parentId + " ul li.orden[data-ordenId='0'][data-formato='"+formato+"']");
				jQuery(vacia).insertAfter(jQuery(ultima));
				}			
			}
		}
	};
